﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Chapter08
{
    using System.Diagnostics;

    partial class Program
    {
        internal static void Begin(Action action, bool active = false)
        {
            if (active)
            {
                Console.WriteLine("开始演示：");
                action();
                Console.WriteLine("演示完毕：");
                Console.ReadLine();
            }
        }

        private class SomeType
        {
            private static int xx = 5;
            private int x;
            private string s;
            private double d;
            private byte b;

            static SomeType()
            {
                Console.WriteLine(xx);
                Console.ReadLine();
            }

            internal SomeType()
                : base()
            {
                x = 5;
                s = "Hi there";
                d = 3.14159;
                b = 0xff;
            }

            internal SomeType(int x)
                : this()
            {
                this.x = x;
            }

            internal SomeType(string s)
                : this()
            {
                this.s = s;
            }

            internal SomeType(int x, string s)
                : this()
            {
                this.x = x;
                this.s = s;
            }

            internal SomeType(int x, string s, double d, byte b)
            {
                this.x = x;
                this.s = s;
                this.d = d;
                this.b = b;
            }
        }

        private struct Point
        {
            internal int x, y;

            internal Point(int x)
            {
                this = new Point();
                this.x = x;
            }

            internal Point(int x, int y)
            {
                this.x = x;
                this.y = y;
            }
        }

        private sealed class Rectangle
        {
            internal Point topLeft, bottomRight;

            internal Rectangle()
            {
                topLeft = new Point(1, 2);
                bottomRight = new Point(100, 200);
            }
        }

        private sealed class SomeRefType
        {
            static SomeRefType()
            {

            }
        }

        internal static void C03()
        {
            SomeType some = new SomeType();
            SomeValType[] a = new SomeValType[10];
            a[0].x = 123;
            Console.WriteLine(a[0].x);
            const int iterations = 1000 * 1000 * 1000;
            PerfTest1(iterations);
            PerfTest2(iterations);
        }

        private struct SomeValType
        {
            internal int x;

            internal SomeValType(int x)
            {
                this.x = x;
            }

            static SomeValType()
            {
                Console.WriteLine("这句话永远不会显示");
            }
        }

        private sealed class BeforeFieldInit
        {
            internal static int x = 123;
        }

        private sealed class Precies
        {
            internal static int x;

            static Precies()
            {
                x = 123;
            }
        }

        private static void PerfTest1(int iterations)
        {
            Stopwatch sw = Stopwatch.StartNew();
            for (int i = 0; i < iterations; i++)
            {
                BeforeFieldInit.x = 1;
            }
            Console.WriteLine("PerfTest1: {0} BeforeFieldInit", sw.Elapsed);
            sw = Stopwatch.StartNew();
            for (int i = 0; i < iterations; i++)
            {
                Precies.x = 1;
            }
            Console.WriteLine("PerfTest1: {0} Precies", sw.Elapsed);
        }

        private static void PerfTest2(int iterations)
        {
            Stopwatch sw = Stopwatch.StartNew();
            for (int i = 0; i < iterations; i++)
            {
                BeforeFieldInit.x = 1;
            }
            Console.WriteLine("PerfTest2: {0} BeforeFieldInit", sw.Elapsed);
            sw = Stopwatch.StartNew();
            for (int i = 0; i < iterations; i++)
            {
                Precies.x = 1;
            }
            Console.WriteLine("PerfTest2: {0} Precies", sw.Elapsed);
        }

        private sealed class Complex
        {
            public static Complex operator +(Complex c1, Complex c2)
            {
                return new Complex();
            }
        }

        internal static void C05()
        {
            Rational r1 = 5;
            Rational r2 = 2.5f;
        }

        private sealed class Rational
        {
            internal Rational(int num) { }
            internal Rational(float num) { }
            internal int ToInt32() { return 0; }
            internal int ToSingle() { return 0; }
            public static implicit operator Rational(int num) { return new Rational(num); }
            public static implicit operator Rational(float num) { return new Rational(num); }
            public static explicit operator int(Rational r) { return r.ToInt32(); }
            public static explicit operator float(Rational r) { return r.ToSingle(); }
        }

        internal static void C06()
        {
            {
                StringBuilder sb = new StringBuilder("Hello. My name is Jeff.");
                int index = StringBuilderExtensions.IndexOf(sb.Replace('.', '!'), '!');
                Console.WriteLine(index);
                sb.Replace('.', '!');
            }
            {
                StringBuilder sb = new StringBuilder("Hello. My name is Jeff.");
                Console.WriteLine(sb.Replace('.', '!').IndexOf('!'));
                Console.WriteLine(sb.IndexOf('X'));
            }
            {
                try
                {
                    StringBuilder sb = null;
                    sb.IndexOf('X');
                    sb.Replace('.', '!');
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }

            }
            {
                "Grant".ShowItems();
                new[] { "Jeff", "Kristin" }.ShowItems();
                new List<int> { 1, 2, 3 }.ShowItems();
            }
            {
                Action a = "Jeff".ShowItems;
                a();
            }
        }

        private class Base
        {
            private string name;

            protected virtual void OnNameChanging(string value) { }

            internal string Name
            {
                get { return name; }
                set
                {
                    OnNameChanging(value.ToUpper());
                    name = value;
                }
            }
        }

        private class Deriveed : Base
        {
            protected override void OnNameChanging(string value)
            {
                if (string.IsNullOrEmpty(value))
                    throw new ArgumentNullException("value");
            }
        }
    }

    internal static class StringBuilderExtensions
    {
        internal static int IndexOf(this StringBuilder sb, char value)
        {
            for (int i = 0; i < sb.Length; i++)
                if (sb[i] == value)
                    return i;
            return -1;
        }

        internal static void ShowItems<T>(this IEnumerable<T> collection)
        {
            foreach (var item in collection)
            {
                Console.WriteLine(item);
            }
        }
    }
}
